package com.lujianfei.netease_android_canvas.widget

import android.content.Context
import android.graphics.*
import android.os.Handler
import android.util.AttributeSet
import com.lujianfei.netease_android_canvas.R
import java.lang.Thread.sleep
import java.util.*
import java.util.concurrent.LinkedBlockingDeque

class LoadingLogo : androidx.appcompat.widget.AppCompatImageView {

    private var running: Boolean = false // 控制线程动画循环结束
    private var result: Bitmap? = null  // 显示 bitmap
    private var maskRes: Bitmap? = null // 遮罩 bitmapffyc
    private var pixels: Array<Array<Int>>? = null // 以二维数组形式存放色值，便于判断及操作 bitmap
    private var backupPixels: IntArray? = null // 用于备份 bitmap 被改变前的色值
    private var queue: Queue<Int> = LinkedBlockingDeque() // 阻塞队列，用于切换颜色时，避免色值与切换前冲突
    private val mHandler = Handler {
        setImageBitmap(result)
        false
    }

    constructor(context: Context?) : super(context) {
        init()
    }

    constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs) {
        init()
    }

    private fun init() {
        scaleType = ScaleType.CENTER_INSIDE
        maskRes = BitmapFactory.decodeResource(resources, R.mipmap.logo)
        maskRes?.let { maskResAfterCheck ->
            pixels = Array(maskResAfterCheck.width) { Array<Int>(maskResAfterCheck.height) { 0 } }
            backupPixels = IntArray(maskResAfterCheck.width * maskResAfterCheck.height)
            setColor(0xffffff00.toInt())
        }
    }

    fun startLoading() {
        if (running) {
            return
        }
        running = true
        Thread {
            while (running) {
                while (queue.size > 1) { // 超过1个则丢弃，保证连续切换颜色后，会直接切到最终的颜色
                    queue.poll()
                }
                if (queue.isNotEmpty()) { // 队列里有色值，则取出执行
                    val poll = queue.poll()
                    setColor(poll)
                }
                updateBitmap() {
                    // 每更新显示位图
                    sleep(1)
                    mHandler.sendEmptyMessage(0)
                }
                sleep(500)
                restorePixels() // 恢复原有色值
                mHandler.sendEmptyMessage(0)
            }
        }.start()
    }

    fun stopLoading() {
        running = false
        mHandler.removeCallbacksAndMessages(null)
    }

    fun postColor(color: Int) {
        queue.offer(color)
    }

    private fun setColor(color: Int) {
        var mask: Bitmap? = null
        maskRes?.let { maskResAfterCheck ->
            val width = maskResAfterCheck.width
            val height = maskResAfterCheck.height
            mask = Bitmap.createBitmap(maskResAfterCheck, 0, 0, width, height)
        }
        mask?.let { maskAfterCheck ->
            result = Bitmap.createBitmap(maskAfterCheck.width, maskAfterCheck.height, Bitmap.Config.ARGB_8888)
            result?.let { resultAfterCheck ->
                //将遮罩层的图片放到画布中
                val mCanvas = Canvas(resultAfterCheck)
                val paint = Paint(Paint.ANTI_ALIAS_FLAG)
                //设置两张图片相交时的模式 
                paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.DST_IN)
                mCanvas.drawColor(color)
                mCanvas.drawBitmap(maskAfterCheck, 0f, 0f, paint)
                paint.xfermode = null
                setImageBitmap(resultAfterCheck)
                backupPixels()
            }
        }
    }

    private fun backupPixels() {
        result?.let { resultAfterCheck ->
            resultAfterCheck.getPixels(backupPixels, 0, resultAfterCheck.width, 0, 0, resultAfterCheck.width, resultAfterCheck.height)
            for (i in 0 until resultAfterCheck.width) {
                for (j in 0 until resultAfterCheck.height) {
                    pixels?.let { pixelsAfterCheck ->
                        pixelsAfterCheck[i][j] = resultAfterCheck.getPixel(i, j)
                    }
                }
            }
        }
    }

    private fun restorePixels() {
        result?.let { resultAfterCheck ->
            resultAfterCheck.setPixels(backupPixels, 0, resultAfterCheck.width, 0, 0, resultAfterCheck.width, resultAfterCheck.height)
        }
    }

    fun updateBitmap(callback: () -> Unit) {
        result?.let { resultAfterCheck ->
            for (i in 0 until resultAfterCheck.width) {
                for (j in 0 until resultAfterCheck.height) {
                    pixels?.let { pixelsAfter ->
                        if (0 != pixelsAfter[i][j]) {
                            resultAfterCheck.setPixel(i, j, 0xa2ffffff.toInt())
                        }
                    }
                }
                callback()
            }
        }
    }
}